Dijkstra’s algorithm for weighted Graphs¶
NOTE: Dijkstra’s algorithm ONLY works with directed acyclic graphs,
(called DAGs for short) and lets you answer "What’s the shortest
path to X?".
def find_lowest_cost_node(costs, processed):
lowest_cost = float("inf")
lowest_cost_node = None
# Go through each node
for node in costs:
cost = costs[node]
if cost < lowest_cost \
and node not in processed:
lowest_cost = cost # set it as the new lowest-cost node
lowest_cost_node = node
return lowest_cost_node
def deijkstra_search(graph, costs, parents):
processed = []
# array to keep track of all the nodes you’ve already processed
# Find the lowest-cost node that you haven’t processed yet
node = find_lowest_cost_node(costs, processed)
# If you’ve processed all the nodes, this while loop is done
while not node is None:
total = costs[node]
neighbors = graph[node]
# Go through all the neighbors of this node
for neibor_node in neighbors.keys():
new_cost = total + neighbors[neibor_node]
# If it’s cheaper to get to this neighbor by going through this node
if costs[neibor_node] > new_cost:
# Update the cost for this node
costs[neibor_node] = new_cost
# This node becomes the new parent for this neighbor
parents[neibor_node] = node
# Mark the node as processed
processed.append(node)
# Find the next node to process, and loop
node = find_lowest_cost_node(costs, processed)
return total
Test¶
A
^ ^ \
6 / | \ 1
/ | v
start | 3 fin
\ | ^
2 \ | / 5
v | /
B
_graph = {}
_graph["start"] = {}
_graph["start"]["A"] = 6
_graph["start"]["B"] = 2
_graph["A"] = {}
_graph["A"]["fin"] = 1
_graph["B"] = {}
_graph["B"]["A"] = 3
_graph["B"]["fin"] = 5
_graph["fin"] = {} # The finish node doesn’t have any neighbors
# print(_graph)
# {'start': {'A': 6, 'B': 2},
# 'A': {'fin': 1},
# 'B': {'A': 3, 'fin': 5},
# 'fin': {}
# }
_costs = {}
_costs["A"] = 6
_costs["B"] = 2
_costs["fin"] = float("inf") # infinity
# print(_costs) # {'A': 6, 'B': 2, 'fin': inf}
_parents = {}
_parents["A"] = "start"
_parents["B"] = "start"
_parents["fin"] = None
# print(_parents) # {'A': 'start', 'B': 'start', 'fin': None}
cost = deijkstra_search(_graph, _costs, _parents)
print("The lower cost from 'start' to 'fin' is: {}".format(cost))
print("The shortest path from 'start' to 'fin' is:")
path = sorted(_costs.items(), key=lambda kv: kv[1])
print("start -> ", end="")
for i in range(len(path)):
print(path[i][0], end=" -> ")